package com.zj.common.adapter

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.paging.LoadState
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.zj.common.listener.State

abstract class BasePagingAdapter<T : Any, VDB : ViewDataBinding> :
    PagingDataAdapter<T, BasePagingAdapter<T, VDB>.BaseViewHolder<VDB>> {
    constructor() : super(itemCallback())

    constructor(diffCallback: DiffUtil.ItemCallback<T>) : super(diffCallback)

    companion object {
        fun <T> itemCallback(
            areItemsTheSame: (T, T) -> Boolean = { o, n -> o == n },
            areContentsTheSame: (T, T) -> Boolean = { o, n -> o == n },
            getChangePayload: (T, T) -> Any? = { _, _ -> null }
        ): DiffUtil.ItemCallback<T> {
            return object : DiffUtil.ItemCallback<T>() {
                override fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
                    return areItemsTheSame(oldItem, newItem)
                }

                override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
                    return areContentsTheSame(oldItem, newItem)
                }

                override fun getChangePayload(oldItem: T, newItem: T): Any? {
                    return getChangePayload(oldItem, newItem)
                }
            }
        }
    }

    override fun onBindViewHolder(holder: BaseViewHolder<VDB>, position: Int) {
        onBind(
            holder,
            position,
            DataBindingUtil.getBinding(holder.itemView),
            holder.itemView.context
        )
    }

    override fun onBindViewHolder(
        holder: BaseViewHolder<VDB>,
        position: Int,
        payloads: MutableList<Any>
    ) {
        // 局部刷新为空时调用item刷新
        if (payloads.isEmpty()) {
            onBindViewHolder(holder, position)
        } else {
            // 局部刷新
            onBind(
                holder,
                position,
                DataBindingUtil.getBinding(holder.itemView),
                holder.itemView.context,
                payloads
            )
        }
    }

    abstract fun onBind(
        holder: BaseViewHolder<VDB>,
        position: Int,
        binding: VDB?,
        context: Context,
        payloads: MutableList<Any>? = null
    )

    /**
     * 绑定布局文件
     */
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<VDB> {
        return BaseViewHolder(
            DataBindingUtil.inflate(
                LayoutInflater.from(parent.context),
                viewType,
                parent,
                false
            )
        )
    }


    override fun getItemViewType(position: Int): Int {
        return getItemLayout(position)
    }


    /**
     * 获取条目类型的布局
     *
     * @param position 索引
     * @return 布局id
     */
    @LayoutRes
    protected abstract fun getItemLayout(position: Int): Int

    // item 点击点击
    private lateinit var onItemClickListener: (adapter: BasePagingAdapter<T, VDB>, view: View, position: Int) -> Unit

    // item 长按
    private lateinit var onItemLongClickListener: (adapter: BasePagingAdapter<T, VDB>, view: View, position: Int) -> Unit

    /**
     * 刷新状态监听
     */
    private lateinit var mOnRefreshStateListener: (State) -> Unit

    /**
     * 向后加载更多状态监听
     */
    private lateinit var mOnLoadMoreStateListener: (State) -> Unit

    /**
     * 向前加载更多监听
     */
    private lateinit var mOnPrependStateListener: (State) -> Unit

    init {
        addLoadStateListener {
            if (::mOnRefreshStateListener.isInitialized) {
                dispatchState(
                    it.refresh,
                    it.source.append.endOfPaginationReached,
                    mOnRefreshStateListener
                )
            }
            if (::mOnLoadMoreStateListener.isInitialized) {
                dispatchState(
                    it.append,
                    it.source.append.endOfPaginationReached,
                    mOnLoadMoreStateListener
                )
            }
            if (::mOnPrependStateListener.isInitialized) {
                dispatchState(
                    it.prepend,
                    it.source.append.endOfPaginationReached,
                    mOnPrependStateListener
                )
            }
        }

    }


    private fun dispatchState(
        loadState: LoadState,
        noMoreData: Boolean,
        stateListener: (State) -> Unit
    ) {
        when (loadState) {
            is LoadState.Loading -> {
                stateListener(State.Loading)
            }
            is LoadState.NotLoading -> {
                stateListener(State.Success(noMoreData))
            }
            is LoadState.Error -> {
                stateListener(State.Error)
            }
        }
    }

    /**
     * 刷新状态监听
     */
    fun setOnRefreshStateListener(listener: (State) -> Unit) {
        mOnRefreshStateListener = listener
    }

    /**
     * 向后加载更多状态监听
     */
    fun setOnLoadMoreStateListener(listener: (State) -> Unit) {
        mOnLoadMoreStateListener = listener
    }

    /**
     * 向前加载更多状态监听
     */
    fun setOnPrependStateListener(listener: (State) -> Unit) {
        mOnPrependStateListener = listener
    }

    /**
     * item 条目点击事件
     */
    fun setOnItemClickListener(listener: (adapter: BasePagingAdapter<T, VDB>, view: View, position: Int) -> Unit) {
        onItemClickListener = listener
    }

    /**
     * item 条目长按事件
     */
    fun setOnItemLongClickListener(listener: (adapter: BasePagingAdapter<T, VDB>, view: View, position: Int) -> Unit) {
        onItemLongClickListener = listener
    }


    /**
     * 内部类
     */
    inner class BaseViewHolder<VDB : ViewDataBinding>(item: VDB) :
        RecyclerView.ViewHolder(item.root), View.OnClickListener,
        View.OnLongClickListener {
        // item中控件view的点击事件
        private val clickListenerCache = ArrayList<View>()

        // item中控件view的长按事件
        private val longClickListenerCache = ArrayList<View>()

        init {
            // item添加点击与长按事件
            itemView.setOnClickListener(this)
            itemView.setOnLongClickListener(this)
        }

        override fun onClick(view: View) {
            if (::onItemClickListener.isInitialized) {
                onItemClickListener.invoke(this@BasePagingAdapter, view, bindingAdapterPosition)
            }
        }

        override fun onLongClick(view: View): Boolean {
            if (::onItemLongClickListener.isInitialized) {
                onItemLongClickListener.invoke(this@BasePagingAdapter, view, bindingAdapterPosition)
                return true
            }
            return false
        }

        /**
         * 给条目中的view添加点击事件
         *
         * @param view 控件View
         */
        fun addOnClickListener(view: View) {
            val contains = clickListenerCache.contains(view)
            if (!contains) {
                view.setOnClickListener(this)
                clickListenerCache.add(view)
            }
        }

        /**
         * 给条目中的view添加长按事件
         *
         * @param view 控件View
         */
        fun addOnLongClickListener(view: View) {
            val contains = longClickListenerCache.contains(view)
            if (!contains) {
                view.setOnLongClickListener(this)
                clickListenerCache.add(view)
            }
        }
    }
}